perm filename RECOG2.SAI[SYS,HE] blob sn#021170 filedate 1973-01-20 generic text, type T, neo UTF8
COMMENT ⊗   VALID 00011 PAGES 
RECORD PAGE   DESCRIPTION
 00001 00001
 00002 00002	ENTRY DUMMY
 00004 00003	α	NEXTL
 00005 00004	α	GNEXTL
 00006 00005	α	COMPARE
 00010 00006	α	MATCHLINES 
 00012 00007	α	FINDX
 00016 00008	α	BASE_EDGES - HEURISTIC BASE DETECTOR
 00021 00009	α	SUPPORT
 00024 00010	α	MAKEPP
 00025 00011	α	FINDEDGELENGTHS
 00030 ENDMK
⊗;
ENTRY DUMMY;

BEGIN "RECOG2.SAI"

REQUIRE		250	PNAMES;
REQUIRE	"PREAMB.SAI[SYS,HE]"	SOURCE_FILE;
REQUIRE	"CPXSYM.AUX[SYS,HE]"	SOURCE_FILE;
REQUIRE	"RECCOM.AUX[SYS,HE]"	SOURCE_FILE;
REQUIRE	"RECDPY.HDR[SYS,HE]"	SOURCE_FILE;

α LOCALS;
INTEGER FLAG,ERRFLAG;

α EXTERNAL PROCEDURES;
ERP		SQRT(REAL X);

EBP		COLINEAR(ITEMVAR L1,L2);
EP		CROSS_PROD(REFERENCE SAFE REAL ARRAY A,B,C);
ERP		DIST(SAFE REAL ARRAY ITEMVAR P1,P2);
ERP		DOT_PROD(REFERENCE SAFE REAL ARRAY A,B);
ESP		GENSYM(INTEGER ITEMVAR X);
EP		INITIALIZE(SAFE REAL ARRAY A);
EP		INVERT(SAFE REAL ARRAY A,AI);
EP		MATMULT(SAFE REAL ARRAY A,B,C; INTEGER N);
EBP		ONLINE(ITEMVAR L;SAFE REAL ARRAY ITEMVAR P);
EBP		PARALLEL(ITEMVAR V1,V2);
ESP		PRINTNAME(ITEMVAR X);
EBP		VERT(ITEMVAR E);
EP		VERT_LINE_PT(SAFE REAL ARRAY ITEMVAR T,B);

EXTERNAL INTEGER
	DDX,DDY;
EXTERNAL REAL
	DISX,DISY,MAGX,MAGY,SDY;

α	NEXTL
returns the next line going from L1 to L2 on face F if there
is one, else returns nil.;

INTERNAL ITEMVAR PROCEDURE NEXTL(ITEMVAR L1,L2,F);
BEGIN "NEXTL"
	  ITEMVAR P,L;
	  SET S;
	  P←COP(ENDPT⊗L2-(ENDPT⊗L1∩ENDPT⊗L2));
	  S ← ENDPT ` P ∩ BOUNDARY ⊗ F ;
	  IF LENGTH (S) = 2 THEN
	   RETURN (COP (S - { L2}))
	    ELSE
	     RETURN(NIL);
       END "NEXTL";

α	GNEXTL
returns the next line going from L1 to L2 on face F if there
is one, elle returns nil.;

INTERNAL ITEMVAR PROCEDURE GNEXTL(ITEMVAR L1,L2,F);
BEGIN "GNEXTL"
	SET STEMP;
	  ITEMVAR P,L;
	  TYPE "GNEXTL - ENTERED" EOM;
	  TYPE TAB&"LINES:"&PRINTNAME(L1)&"  "&PRINTNAME(L2)&
		"  FACE:"&PRINTNAME(F)  EOM;
	  P←COP(GLB ENDPT⊗L2-(GLB ENDPT⊗L1∩ GLB ENDPT⊗L2));
	STEMP←(GLB ENDPT`P) ∩ (GLB BOUNDARY⊗F);
	  IF LENGTH(STEMP)=2
	  THEN BEGIN
	      L←COP(STEMP - {L2});
	      TYPE TAB&"NEXT LINE="&PRINTNAME(L) EOM;
	      RETURN (L);
	   END
	   ELSE
	    RETURN(NIL);
       END "GNEXTL";

α	COMPARE
look at the original camera image and the constructed
graphics image and decide if they are the same ???;

INTERNAL PROCEDURE COMPARE;
BEGIN "COMPARE"
REAL	CXMIN,CXMAX,CYMIN,CYMAX,
	GXMIN,GXMAX,GYMIN,GYMAX,
	XMIN,XMAX,YMIN,YMAX, DX,DY,
	MAGX,MAGY;
SET	GVERTS;
SAFE REAL ARRAY ITEMVAR GP,P;
ITEMVAR GL,L;

CXMIN←GXMIN←CYMIN←GYMIN←1000;
CXMAX←GXMAX←CYMAX←GYMAX←-1000;

∀ GL|$ LINE⊗SCENE≡GL DO
⊂ L←NEW; MAKE LINE⊗GL≡L ⊃;

∀ GP|$ POINT⊗SCENE≡GP DO
⊂ P←NEW($ ∂(GP));
  MAKE POINT⊗GP≡P;
  ∂(P)[2] ← SDY - ∂(P)[2];
  IF ∂(P)[1] < CXMIN
  THEN CXMIN← ∂(P)[1]
  ELSE IF ∂(P)[1] > CXMAX
	THEN CXMAX← ∂(P)[1];
  IF ∂(P)[2] < CYMIN
  THEN CYMIN← ∂(P)[2]
  ELSE IF ∂(P)[2] > CYMAX
       THEN CYMAX← ∂(P)[2] ⊃;
TYPE "CAMERA XMIN="&CVG(CXMIN)&" CXMAX="&CVG(CXMAX)&↓&
	TAB&"CAMERA YMIN="&CVG(CYMIN)&" CYMAX="&CVG(CYMAX) EOM;

∀ GP,P|$ POINT⊗SCENE≡GP ∧ POINT⊗GP≡P DO
⊂ ∂(P)[1]←∂(P)[1]-CXMIN;
  ∂(P)[2]←∂(P)[2]-CYMIN ⊃;

GVERTS←PHI;
∀ GL|$ VISIBLE⊗SCENE≡GL DO
⊂ GVERTS←GVERTS ∪ $ ENDPT⊗GL;
  L←NEW; MAKE VISIBLE⊗GL≡L ⊃;

∀ GP|GPεGVERTS DO
⊂ P←NEW($ ∂(GP));
  MAKE VISIBLE⊗GP≡P;
  IF $ ∂(GP)[1] < GXMIN
  THEN GXMIN← $ ∂(GP)[1]
  ELSE IF $ ∂(GP)[1] > GXMAX
	THEN GXMAX← $ ∂(GP)[1];
  IF $ ∂(GP)[2] < GYMIN
  THEN GYMIN←$ ∂(GP)[2]
  ELSE IF $ ∂(GP)[2] > GYMAX
       THEN GYMAX←$ ∂(GP)[2] ⊃;

∀ GP,P|GPεGVERTS ∧ VISIBLE⊗GP≡P DO
⊂ ∂(P)[1]←∂(P)[1]-GXMIN;
  ∂(P)[2]←∂(P)[2]-GYMIN ⊃;
TYPE "GRAPHIC XMIN="&CVG(GXMIN)&" GXMAX="&CVG(GXMAX)&↓&
	TAB&"GRAPHIC YMIN="&CVG(GYMIN)&" GYMAX="&CVG(GYMAX) EOM;

XMIN← CXMIN MIN GXMIN;
XMAX← CXMAX MAX GXMAX;
YMIN← CYMIN MIN GYMIN;
YMAX← CYMAX MAX GYMAX;
DX←XMAX-XMIN + 10;
DY←YMAX-YMIN + 10;
MAGX←MAGY←(IF DX/DY > 1 THEN DDX/DX ELSE DDY/DY);
DISX← 5;
DISY← 5;
TYPE "DISX="&CVG(DISX)&TAB&"DISY="&CVG(DISY) EOM;

∀ GP,P|$ POINT⊗SCENE≡GP ∧ POINT⊗GP≡P DO
⊂ ∂(P)[6]← MAGX*∂(P)[1]+DISX;
  ∂(P)[7]← MAGY*∂(P)[2]+DISY ⊃;

∀ GP,P|GPεGVERTS ∧ VISIBLE⊗GP≡P DO
⊂ ∂(P)[6]← MAGX*∂(P)[1]+DISX;
  ∂(P)[7]← MAGY*∂(P)[2]+DISY ⊃;

DPYSET(DPYAA);
DPYBIG(TEXT);
∀ GP,P|$ POINT⊗SCENE≡GP ∧ POINT⊗GP≡P DO
⊂ AIVECT(#X(P),#Y(P)); DPYSST("O") ⊃;
DPYOUT(APOG);
DPYLAB("THE CAMERA SCENE.");
DPYSET(DPYAA);
DPYBIG(TEXT);
∀ GP,P|GPεGVERTS ∧ VISIBLE⊗GP≡P DO
⊂ AIVECT(#X(P),#Y(P)); DPYSST("x") ⊃;
DPYOUT(BPOG);
DPYINFO("WAITING");
DPYLAB("ADD THE GRAPHIC SCENE.");
END "COMPARE";

α	MATCHLINES 
matches lines on F and MF.
F is an object face and MF is a model face.
L1 and L2 on object match ML1 and ML2 on model respectively.;

INTERNAL PROCEDURE MATCHLINES(ITEMVAR F,MF,L1,L2,ML1,ML2);
BEGIN "MATCHLINES"
	  ITEMVAR L,LX,MLX,ML,MLA,MLB,LA,LB;
	  TYPE "MATCHLINES - ENTERED"&↓&
		TAB&"BODY FACE:"&PRINTNAME(F)&↓&
		TAB&"BODY LINES:"&PRINTNAME(L1)&"  "&PRINTNAME(L2)&↓&
		TAB&"MODEL FACE:"&PRINTNAME(MF)&↓&
		TAB&"MODEL LINES:"&PRINTNAME(ML1)&"  "&PRINTNAME(ML2) EOM;

	  LX←L2; MLX←ML2;
	  L←NEXTL(L1,L2,F); ML←GNEXTL(ML1,ML2,MF);
	  WHILE L≠L1 ∧ L≠NIL DO
	   BEGIN
	      IF ¬MATCH⊗L≡ANY THEN MAKE MATCH⊗L≡ML;
	      LA←LX;
	      LX←LB←L;
	      L←NEXTL(LA,LB,F);
	      MLA←MLX;
	      MLX←MLB←ML;
	      ML←GNEXTL(MLA,MLB,MF);
	   END;
	  IF L=L1
	  THEN BEGIN
		TYPE TAB&"RETURN FROM MATCHLINES (1)" EOM;
		RETURN;
		END;
	  L1↔L2; ML1↔ML2;
	  LX←L2; MLX←ML2;
	  L←NEXTL(L1,L2,F); ML←GNEXTL(ML1,ML2,MF);
	  WHILE L≠L1 ∧ L≠NIL DO
	   BEGIN
	      IF ¬MATCH⊗L≡ANY THEN MAKE MATCH⊗L≡ML;
	      LA←LX;
	      LX←LB←L;
	      L←NEXTL(LA,LB,F);
	      MLA←MLX;
	      MLX←MLB←ML;
	      ML←GNEXTL(MLA,MLB,MF);
	   END;
	  TYPE TAB&"RETURN FROM MATCHLINES (2)" EOM;

	  RETURN;
       END "MATCHLINES";

α	FINDX
finds the 4X4 translation-rotation matrix necessary to take 
MX1,MX2,MX3 of prototype P into X1,X2,X3 of body B.;

INTERNAL PROCEDURE FINDX(SAFE REAL ARRAY ITEMVAR B,P,X1,X2,X3,MX1,MX2,MX3);
BEGIN "FINDX"
INTEGER I,J;
REAL MAG,MAGV2,MAGV3,MAGMV2,MAGMV3;
SAFE REAL ARRAY ITEMVAR X,GB;
SAFE REAL ARRAY MX2R,V2,V3,MV2,MV3,U1,U2,U3,MU1,MU2,MU3[1:3];
SAFE REAL ARRAY R1,R2,R2T,R[1:3,1:3],TT[1:4,1:4];

TYPE "FINDX - ENTER" EOM;
TYPE TAB&"BODY:"&PRINTNAME(B)&↓&
	TAB&"PROTOTYPE:"&PRINTNAME(P) EOM;
MAGV2←MAGV3←MAGMV2←MAGMV3←0.0;
FOR I←1 S1U 3 DO
BEGIN
	V2[I]←∂(X1)[I+2]-∂(X2)[I+2];
	V3[I]←∂(X3)[I+2]-∂(X2)[I+2];
	MV2[I]←GLB ∂(MX1)[I]-GLB ∂(MX2)[I];
	MV3[I]←GLB ∂(MX3)[I]-GLB ∂(MX2)[I];
	MAGV2←MAGV2+V2[I]↑2;
	MAGV3←MAGV3+V3[I]↑2;
	MAGMV2←MAGMV2+MV2[I]↑2;
	MAGMV3←MAGMV3+MV3[I]↑2;
	END;

IF MAGV3 > MAGV2
THEN BEGIN
	MAGV2↔MAGV3;
	MAGMV2↔MAGMV3;
	FOR I←1 S1U 3 DO
	BEGIN
		V2[I]↔V3[I];
		MV2[I]↔MV3[I];
		END;
	END;

FOR I←1 S1U 3 DO
BEGIN
	U2[I]←V2[I]/SQRT(MAGV2);
	U3[I]←V3[I]/SQRT(MAGV3);
	MU2[I]←MV2[I]/SQRT(MAGMV2);
	MU3[I]←MV3[I]/SQRT(MAGMV3);
	END;

CROSS_PROD(U3,U2,U1);
MAG←SQRT(DOT_PROD(U1,U1));
FOR I←1 S1U 3 DO U1[I]←U1[I]/MAG;
CROSS_PROD(MU3,MU2,MU1);
MAG←SQRT(DOT_PROD(MU1,MU1));
FOR I←1 S1U 3 DO MU1[I]←MU1[I]/MAG;
CROSS_PROD(U2,U1,U3);
CROSS_PROD(MU2,MU1,MU3);
FOR I←1 S1U 3 DO
BEGIN
	R1[I,1]←U1[I];
	R1[I,2]←U2[I];
	R1[I,3]←U3[I];
	R2[I,1]←MU1[I];
	R2[I,2]←MU2[I];
	R2[I,3]←MU3[I];
	END;

FOR I←1 S1U 3 DO
	FOR J←1 S1U 3 DO R2T[I,J]←R2[J,I];
MATMULT(R1,R2T,R,3);
FOR I←1 S1U 3 DO
BEGIN
	MAG←SQRT(R[I,1]↑2 + R[I,2]↑2 + R[I,3]↑2);
	FOR J←1 S1U 3 DO R[I,J]←R[I,J]/MAG;
	END;
FOR I←1 S1U 3 DO
	FOR J←1 S1U 3 DO TT[I,J]←R[I,J];
TT[4,1]←TT[4,2]←TT[4,3]←0.0;TT[4,4]←1.0;
FOR I←1 S1U 3 DO
BEGIN
	MX2R[I]←0.0;
	FOR J←1 S1U 3 DO MX2R[I]←MX2R[I]+R[I,J]*GLB ∂(MX2)[J];
	END;
FOR I←1 S1U 3 DO TT[I,4]←∂(X2)[I+2]-MX2R[I];
TYPE TAB&"INSTANCE TRANSFORM FOR BODY:" EOM;
FOR I←1 S1U 4 DO
TYPE TAB&CVG(TT[I,1])&"  "&CVG(TT[I,2])&"  "&CVG(TT[I,3])&"  "&CVG(TT[I,4]) EOM;

GB←GLB NEW(TT);
MAKE OMATCH⊗GB≡B;
GLB MAKE INSTANCE⊗P≡GB;
X←GLB NEW(FOURBY4);
GLB MAKE INVERSE⊗GB≡X;
INVERT(TT,GLB ∂(X));
TYPE TAB&"FINDX - EXIT" EOM;
END "FINDX";
α	BASE_EDGES - HEURISTIC BASE DETECTOR
;

INTERNAL SET PROCEDURE BASE_EDGES(ITEMVAR B);
BEGIN "BASE EDGES"
SET ITEMVAR BS;
ITEMVAR L,F,L1,L2;
STRING STR1;
SET S,S1,S2,S3,S4;
SAFE REAL ARRAY ITEMVAR P,W,X,Y,TOP,BOTTOM,Z,V1,V2,V3;
REAL SLOPE1,SLOPE2;

α only exterior edges are candidates for base edges;

TYPE "BASE_EDGES - ENTERED" EOM;
ASSIGN BS|EXTERIOR⊗B≡BS HOLDS;
S←∂(BS);
TYPE TAB&"EXTERIOR EDGES: " EOS;
∀ X|XεS DO TYPE PRINTNAME(X)&" " EOS;
TYPE "DONE" EOM;


α exclude vertical edges from potential base edges;

S1←PHI;

S2←LINE⊗B;
∀ X|XεS DO
IF VERT(X)
 THEN BEGIN
	LABEL LAB1;
	S3←ENDPT⊗X;
	TOP←LOP(S3);
	BOTTOM←COP(S3);
	IF ∂(TOP)[2]<∂(BOTTOM)[2]
	 THEN TOP↔BOTTOM;
	IF LENGTH(( ENDPT`BOTTOM)∩(LINE⊗B))=3
	 THEN GO TO LAB1;
	PUT X IN S1;
	IF XεS
	 THEN REMOVE X FROM S;
LAB1:
	END;

α also exclude edges adjacent to the vertical edges at their tops;

∀ X | XεS DO
 ∀ Y | YεS1 DO
  BEGIN
	S2←(ENDPT⊗X)∩(ENDPT⊗Y);
	IF S2≠PHI
	 THEN BEGIN
		S3←ENDPT⊗Y;
		TOP←LOP(S3);
		BOTTOM←COP(S3);
		IF ∂(TOP)[2]<∂(BOTTOM)[2]
		 THEN TOP↔BOTTOM;
		Z←COP(S2);
		IF Z=TOP
		 THEN BEGIN
			REMOVE X FROM S;
			PUT X IN S1;
			DONE;
			END;
		END;
	END;

α remove edges at "concave down" L vertices;

S2←POINT⊗B;
∀ V3|V3εS2 DO
BEGIN
	S3←ENDPT`V3∩LINE⊗B;
	IF LENGTH(S3)=2
	THEN BEGIN
		X←LOP(S3);
		S4←ENDPT⊗X;
		REMOVE V3 FROM S4;
		V1←COP(S4);
		Y←COP(S3);
		S4←ENDPT⊗Y;
		REMOVE V3 FROM S4;
		V2←COP(S4);
		IF ∂(V3)[2]≥∂(V1)[2] ∧ ∂(V3)[2]≥∂(V2)[2]
		THEN BEGIN
			S←S-{X,Y};
			PUT X IN S1;
			PUT Y IN S1;
			END;
		END;
	END;

α remove edges at "concave down" exterior ARROW vertices.;

∀ L,P|LεS ∧ ENDPT⊗L≡P ∧ FLAVOR⊗P≡ARROW DO
BEGIN
	ASSIGN Y|ENDPT⊗Y≡P ∧ (YεSHAFTS) HOLDS;
	V1←COP(ENDPT⊗Y-{P});
	IF ∂(V1)[7]<∂(P)[7]
	THEN BEGIN
		S4←ENDPT`P∩LINE⊗B-SHAFTS;
		X←LOP(S4);
		Y←COP(S4);
		S←S-{X,Y};
		PUT X IN S1;
		PUT Y IN S1;
		END;
	END;

α if colinear segments have not yet been extended, do not
let one part of an edge be part of the base and another
part not be part of the base.;

∀ X,Y| XεS AND YεS1 AND (COLINEAR(X,Y)) DO
BEGIN
	REMOVE X FROM S;
	PUT X IN S1;
	END;

α don't keep two lines as base edges on any one visible face.;

∀ F|FACE⊗B≡F DO
BEGIN
	S2←BOUNDARY⊗F∩S;
	IF LENGTH(S2)>1
	THEN BEGIN
		L1←LOP(S2);L2←COP(S2);
		S2←ENDPT⊗L1;
		X←LOP(S2);
		Y←COP(S2);
		S2←ENDPT⊗L2;
		Z←LOP(S2);
		W←COP(S2);

		SLOPE1←(∂(X)[2]-∂(Y)[2])/(∂(X)[1]-∂(Y)[1]);
		SLOPE2←(∂(Z)[2]-∂(W)[2])/(∂(Z)[1]-∂(W)[1]);
		IF ABS(SLOPE1)>ABS(SLOPE2)
		THEN REMOVE L1 FROM S
		ELSE REMOVE L2 FROM S;
		END;
	END;

α subject to applied heuristics set S contains the "base" edges
of the body.;

STR1←PRINTNAME(B);

IF S=PHI
THEN TYPE TAB&"NO BASE EDGES VISIBLE FOR BODY "&STR1 EOM
ELSE ∀ X| XεS DO
BEGIN
	S4←ENDPT⊗X;
	V1←LOP(S4);
	V2←COP(S4);
	TYPE TAB&"BASE EDGE OF BODY "&STR1&" IS "&PRINTNAME(X)
		  &"  ("&PRINTNAME(V1)&","&PRINTNAME(V2)&")" EOM;
	END;

S1←S2←S3←S4←PHI;
RETURN (S);

END "BASE EDGES";

α	SUPPORT
the mumbo jumbo which follows is supposed to set up associations 
giving the binary relationships between bodies.
For examble, if object A rests on object B, then we will
hopefully set up an association "SUPPORTER⊗A≡B".
The decisions here are based only on 2-D information.
Later during the recognition process 3-D information
is used to rule out some of the potential supporters.;

INTERNAL PROCEDURE SUPPORT(ITEMVAR B1,B2);
       BEGIN "SUPPORT"
	  ITEMVAR E,L,LA,R2,F2;
	  SET S1,S2;
	  SET ITEMVAR X;
	  STRING STR;

	  ∀ E|EDGE⊗S≡E DO
	   BEGIN
	      LABEL LAB1;
	      IF LENGTH(BOUNDARY`E)=1 THEN GO TO LAB1;
	      L←NEW;
	      NEW_PNAME(L,GENSYM(NEWL));
	      S1←BOUNDARY`E∩AREA⊗B1;
	      S2←BOUNDARY`E∩AREA⊗B2;
	      IF S1≠PHI ∧ S2≠PHI
	       THEN BEGIN
		  ASSIGN X|BASE⊗B1≡X HOLDS;
		  ∀ LA|LAε∂(X) DO
		   IF LA=L ∨ SON⊗LA≡L
		    THEN BEGIN
		       MAKE SUPPORTER⊗B1≡B2;
		       R2←COP(S2);
		       IF LENGTH(AREA`R2∩BODY⊗S)=1
			THEN BEGIN
			   STR←PRINTNAME(R2)[5 TO INF];
			   STR←":"&STR;
			   F2←NEW;NEW_PNAME(F2,STR);
			   IF SON⊗ANY≡F2 THEN F2←COP(SON`F2);
			END
			ELSE IF LENGTH(AREA`R2∩BODY⊗S)=2
			 THEN BEGIN
			    STR←PRINTNAME(R2)[5 TO INF];
			    STR←":"&STR;
			    R2←NEW;NEW_PNAME(R2,STR);
			    ASSIGN F2|FACE⊗B2≡F2 ∧ PARENT⊗F2≡R2 HOLDS;
			 END
			 ELSE BEGIN
			    TYPE "SUPPORT - TOO MANY MISSING LINES." EOM;
			    S1←S2←PHI;
			    RETURN;
			 END;
		       MAKE TOP⊗B2≡F2;
		    END;
	       END;
	   LAB1:
	   END;
	  S1←S2←PHI;
	  RETURN;
       END "SUPPORT";

α	MAKEPP
sets up associations representing the fact that prototype
PRO has a view where V vertices and F faces are visible.
D=0 implies that this is a degenerate view, D=1 says that
the view is not degenerate.;

INTERNAL PROCEDURE MAKEPP(ITEMVAR PRO; INTEGER F,V,D);
       BEGIN "MAKEPP"
	  SAFE INTEGER ARRAY ITEMVAR X;

	  X←NEW(SIZE3);
	  MAKE PPAIR⊗PRO≡X;
	  ∂(X)[1]←F;
	  ∂(X)[2]←V;
	  ∂(X)[3]←D;

       END "MAKEPP";

α	FINDEDGELENGTHS
try to set up the lengths of the various edges of the
scene as the datums of the corresponding edge items.
Edges that are occluded are represented by a length
minus the length of the visible portion.
Only a few of the edge lengths are set up, i.e., base edges,
vertical edges, and lines parallel to edges of known length
and on the same face.;

INTERNAL PROCEDURE FINDEDGELENGTHS(ITEMVAR B);

       BEGIN "FINDEDGELENGTHS"
	  SET ITEMVAR X;
	  SET S;
	  SAFE REAL ARRAY ITEMVAR V1,V2,U,V;
	  REAL ITEMVAR L,Y,F;
	  REAL LEN,IDIST1,IDIST2;
	  BOOLEAN BOOL1;

TYPE "FINDEDGELENGTHS - ENTERED" EOM;
	  ∀ L|LINE⊗B≡L DO ∂(L)←0.0;

α set up the lengths of the base edges;

	  ASSIGN X|BASE⊗B≡X HOLDS;
	  ∀ L|Lε∂(X) DO
	   BEGIN
	      S←ENDPT⊗L;

	      V1←LOP(S);
	      V2←COP(S);
	      LEN←SQRT((∂(V1)[3]-∂(V2)[3])↑2+
	       (∂(V1)[4]-∂(V2)[4])↑2);
	      IF (LENGTH(ENDPT`V1∩LINE⊗B)=1)∨(LENGTH(ENDPT`V2∩LINE⊗B)=1)
	       THEN ∂(L)←-LEN
		ELSE ∂(L)←LEN;
	      TYPE TAB&"BASE EDGE: "&PRINTNAME(V1)&"  "&PRINTNAME(V2)&"  "&CVG(
	       ∂(L)) EOM;
	   END;


α now do the vertical edges.;

	  VERTICALS←PHI;
	  ∀ L|LINE⊗B≡L ∧ (¬LεBASES) DO
	   IF VERT(L) THEN PUT L IN VERTICALS;

	  ∀ L|LεVERTICALS DO
	   BEGIN
	      LABEL L1;
	      BOOL1←FALSE;
	      ∀ Y|Yε∂(X) DO
	       IF ADJ(L,Y) THEN BOOL1←TRUE;
	      IF ¬BOOL1 THEN GO TO L1;
	      S←ENDPT⊗L;
	      U←LOP(S);
	      V←COP(S);
	      TYPE TAB&"Z COOR:"&CVG(∂(U)[5])&"  "&CVG(∂(V)[5]) EOM;
	      IF ∂(U)[2]<∂(V)[2] THEN U↔V;
	      VERT_LINE_PT(U,V);
	      LEN←SQRT((∂(U)[3]-∂(V)[3])↑2+
	       (∂(U)[4]-∂(V)[4])↑2+
		(∂(U)[5]-∂(V)[5])↑2);
	      IF (LENGTH(ENDPT`U∩LINE⊗B)=1)∨(LENGTH(ENDPT`V∩LINE⊗B)=1)
	       THEN ∂(L)←-LEN
		ELSE ∂(L)←LEN;
	      TYPE TAB&"VERTICAL:"&PRINTNAME(U)&" "&PRINTNAME(V)&" "&CVG(∂(L))
	       EOM;
	   L1:
	   END;


α now those edges parallel to edges of known length.;

	  ∀ F|FACE⊗B≡F DO
	   ∀ L|BOUNDARY⊗F≡L DO
	    IF ∂(L)=0 THEN
	     ∀ Y|BOUNDARY⊗F≡Y ∧ (Y≠L) ∧ (ABS(∂(Y))>0)
	      ∧ ((ENDPT⊗L∩ENDPT⊗Y)=PHI) ∧ (PARALLEL(L,Y)) DO
	       BEGIN
		  S←ENDPT⊗Y;
		  U←LOP(S);
		  V←COP(S);
		  IDIST1←DIST(U,V);
		  S←ENDPT⊗L;
		  U←LOP(S);
		  V←COP(S);
		  IDIST2←DIST(U,V);
		  LEN←ABS(∂(Y))*IDIST2/IDIST1;
		  IF (LENGTH(ENDPT`U∩LINE⊗B)=1)∨(LENGTH(ENDPT`V∩LINE⊗B)=1)
		   THEN
		    ∂(L)←-LEN ELSE ∂(L)←LEN;
		  TYPE TAB&"PARALLEL:"&PRINTNAME(U)&" "&PRINTNAME(V)&
			" "&CVG(∂(L)) EOM;
	       END;
	  TYPE TAB&"FINDEDGELENGTHS - EXIT" EOM;
	  S←PHI;
	  RETURN;


       END "FINDEDGELENGTHS";

END "RECOG2.SAI";